#include "sock.h"
#include "protocal.h"
#include <pthread.h>

void handle(const request_t &req, req_result_t *pres)
{
    int num1 = req.num1;
    int num2 = req.num2;
    char op = req.op;
    std::cout << num1 << op << num2;
    switch (op)
    {
    case '+':
        pres->result = num1 + num2;
        break;
    case '-':
        pres->result = num1 - num2;
        break;
    case '*':
        pres->result = num1 * num2;
        break;
    case '/':
        if (num2 == 0)
        {
            pres->exit_code = -1;
        }
        else
        {
            pres->result = num1 / num2;
        }
        break;
    case '%':
        if (num2 == 0)
        {
            pres->exit_code = -2;
        }
        else
        {
            pres->result = num1 % num2;
        }
        break;
    default:
        std::cout << op << "为非法操作符" << std::endl;
        break;
    }
}

void *service_run(void *args)
{
    int sock = *(int *)args;
    request_t req;
    // 方法1
    // ssize_t size = read(sock, &req, sizeof(req));
    // 方法2
    char buffer[1024] = {0};
    ssize_t size = read(sock, buffer, sizeof(buffer));
    buffer[size] = 0;
    std::string json_string = buffer;
    std::cout << json_string << std::cout;
    DeserializeRequest(json_string, &req);

    if (size > 0)
    {
        req_result_t res;
        handle(req, &res);

        std::string json_string = SerializeReqResult(res);
        write(sock, json_string.c_str(), json_string.size());

        //write(sock, &res, sizeof(res));
    }
    else
    {
        std::cout << "client quit" << std::cout;
    }
    return nullptr;

    // read(sock, &res, sizeof(res));
}

void Usage(char *args)
{
    std::cout << "Usage:\n\t" << args << " server.prot" << std::endl;
    exit(1);
}
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
    }
    int sock = Sock::sock();
    uint16_t ser_port = atoi(argv[1]);

    // struct sockaddr_in local;
    // local.sin_family = AF_INET;
    // local.sin_port = htons(ser_port);
    // local.sin_addr.s_addr = INADDR_ANY;

    // Sock::Bind(sock, &local);

    Sock::Bind(sock, ser_port);
    Sock::Listen(sock);

    while (true)
    {
        struct sockaddr_in client;
        socklen_t len = sizeof(client);
        int new_sock = Sock::Accept(sock, &client, &len);
        pthread_t tid;
        pthread_create(&tid, nullptr, service_run, (void *)&new_sock);
    }
    return 0;
}
